package org.jeecg.modules.front.controller;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wechat.pay.java.core.exception.ValidationException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.*;
import org.jeecg.modules.front.entity.vo.*;
import org.jeecg.modules.front.pay.Payment;
import org.jeecg.modules.front.pay.PaymentFactory;
import org.jeecg.modules.front.util.YinShengUtil;
import org.jeecg.modules.fund.entity.*;
import org.jeecg.modules.fund.service.*;
import org.jeecg.modules.gongqiang.entity.MallConfiguration;
import org.jeecg.modules.gongqiang.entity.Userhome;
import org.jeecg.modules.gongqiang.service.IMallConfigurationService;
import org.jeecg.modules.gongqiang.service.IUserhomeService;
import org.jeecg.modules.system.service.impl.SysBaseApiImpl;
import org.jeecg.modules.yinsheng.utils.YsChannelClientException;
import org.jeecg.modules.yinsheng.utils.YsMpPayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author scott
 * @since 2018-12-17
 */
@RestController
@RequestMapping("/front/userHomeOrder")
@Api(tags = "前台用户订单模块")
@Slf4j
public class FrontOrderController {

    @Autowired
    private IUserhomeOrderService userhomeOrderService;

    @Autowired
    private IFundService fundService;

    @Autowired
    private IUserhomeService userhomeService;

    @Autowired
    private IFundTypeService fundTypeService;

    @Autowired
    private IFundSubscriptionRateService fundSubscriptionRateService;

    @Autowired
    private IMallConfigurationService mallConfigurationService;


    @Autowired
    private IUserhomeFundService userhomeFundService;

    @Autowired
    private IUserhomeWalletFundLogService userhomeWalletFundLogService;



    @Autowired
    private SysBaseApiImpl sysBaseApi;


    @ApiOperation("下单")
    @RequestMapping(value = "/buy", method = RequestMethod.POST)
    @Transactional(rollbackFor = Exception.class)
    public Result<UserhomeOrder> createOrder(@RequestBody BuyOrder buyOrder, HttpServletRequest req) {
        Fund fund = fundService.getByIdLock(buyOrder.getFundId());
        Integer userId = JwtUtil.getUserId(req.getHeader("X-Access-Token"));
        Userhome userhome = userhomeService.getById(userId);
        if(userhome.getIsAuthentication()==0)
        {
            return Result.error("账户没用实名制!");
        }
        if (fund == null) {
            return Result.error("基金已下架!");
        }
        if (fund.getStockNum() < buyOrder.getNum()) {
            return Result.error("基金份额不足!");
        }
        if (!fund.getStatus().equals(1)) {
            return Result.error("基金已下架!");
        }
        fund.setStockNum(fund.getStockNum() - buyOrder.getNum());
        fund.setBuyNum(fund.getBuyNum() + buyOrder.getNum());
        fundService.updateById(fund);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        String orderNum = YinShengUtil.OrderNum("FD");
        UserhomeOrder userhomeOrder = new UserhomeOrder();
        userhomeOrder.setCreateBy("自行购买");
        userhomeOrder.setCreateTime(new Date());
        userhomeOrder.setUpdateBy("执行下单");
        userhomeOrder.setUpdateTime(new Date());
        userhomeOrder.setFundId(fund.getId());
        userhomeOrder.setNum(buyOrder.getNum());
        userhomeOrder.setAmount(buyOrder.getNum());
        userhomeOrder.setPayType(0);
        userhomeOrder.setUserhomeId(userId);
        userhomeOrder.setOrderNum(orderNum);
        userhomeOrder.setStatus(0);
        userhomeOrder.setAgreeUrl(buyOrder.getAgreeUrl());
        userhomeOrder.setFundId(fund.getId());
        userhomeOrderService.save(userhomeOrder);
        return Result.ok(userhomeOrder);
    }


    @ApiOperation("支付")
    @RequestMapping(value = "/yinsheng/pay", method = RequestMethod.POST)
    @Transactional(rollbackFor = Exception.class)
    public Result<JSONObject> wxPayOrder(@RequestBody PayOrder payOrder, HttpServletRequest req) throws InstantiationException, IllegalAccessException {
        UserhomeOrder userhomeOrder = userhomeOrderService.getByIdLock(payOrder.getOrderId());
        if (userhomeOrder == null) {
            return Result.error("订单不存在!");
        }
        if (!userhomeOrder.getStatus().equals(0)) {
            return Result.error("订单已不可支付!");
        }
        Fund fund = fundService.getById(userhomeOrder.getFundId());
        if (fund == null) {
            return Result.error("基金已下架!");
        }

        Map<String, String> extendParams = new HashMap<>();
        if(payOrder.getPlatform().equals("Yinsheng")&&payOrder.getWay().equals("scan")&&payOrder.getChannel().equals("wechat"))
        {
            Integer userId = JwtUtil.getUserId(req.getHeader("X-Access-Token"));
            Userhome userhome = userhomeService.getById(userId);
            if (oConvertUtils.isEmpty(userhome.getWoaopenid())) {
                return Result.error("没有获取openid");
            }
            extendParams.put("wxOpenId", userhome.getWoaopenid());
        }
        if(payOrder.getPlatform().equals("Yinsheng")&&payOrder.getWay().equals("bank"))
        {

            extendParams.put("bankType", payOrder.getChannel());
            extendParams.put("payMode", payOrder.getPayMode());
            extendParams.put("bankAccountType", payOrder.getBankAccountType());
        }
        extendParams.put("name", fund.getName());
        PaymentFactory factory = new PaymentFactory();
        Payment payment = factory.createPayment(payOrder.getPlatform(), payOrder.getWay(), payOrder.getChannel());
        try {
            //更新支付类型
            userhomeOrder.setPayType(payment.payType());
            userhomeOrderService.updateById(userhomeOrder);
            //拉起支付
            return payment.pay(userhomeOrder.getOrderNum(), userhomeOrder.getAmount(), extendParams);
        } catch (Exception e) {
            log.warn(e.getMessage());
            return Result.error(e.getMessage());
        }

    }


    @RequestMapping(value = "/yinsheng/notify", method = {RequestMethod.GET, RequestMethod.POST})
    public String yinshengNotify(HttpServletRequest req) throws YsChannelClientException {
        LinkedHashMap<String, String> map = new LinkedHashMap<>();
        Map<String, String[]> requestParams = req.getParameterMap();
        String sign = null;
        for (String name : requestParams.keySet()) {
            String[] values = requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            map.put(name, valueStr);
        }
        //验证签名
        String result = map.entrySet().stream()
                .map(entry -> entry.getKey() + "=" + entry.getValue())
                .collect(Collectors.joining(", "));
        log.info("银盛渠道异步返回[" + result + "]");
        try {
            if (!YsMpPayUtils.verifySign(YinShengUtil.getPubKeyPath(), map, false)) {
                return "error";
            }
            JSONObject jsonObject = JSONObject.parseObject(map.get("bizResponseJson"));
            if (jsonObject.getString("state").equals("SUCCESS")) {
                //处理业务逻辑
                String outTradeNo = jsonObject.getString("requestNo");
                String firstTwoChars = outTradeNo.substring(0, 2);
                String totalAmount = jsonObject.getString("amount");
                String tradeSn = jsonObject.getString("tradeSn");
                Result<JSONObject> returnResult=new Result<>();
                if(firstTwoChars.equals("FD"))
                {
                    //充值回调
                    returnResult=userhomeOrderService.callBack(outTradeNo,totalAmount,tradeSn);
                    Map<String, Object> params=new HashMap<>();
                    params.put("merchantNo", YinShengUtil.getPrdPayeeMerchantNo());
                    params.put("type", 2);
                    params.put("out_trade_no", outTradeNo);
                    params.put("money", totalAmount);
                    YinShengUtil.report(params);
                }
                if(firstTwoChars.equals("JT")||firstTwoChars.equals("FT")||firstTwoChars.equals("MQ")||firstTwoChars.equals("FE"))
                {
                    String str="CZ";
                    if(firstTwoChars.equals("JT"))
                    {
                        str="FA";
                    }
                    if(firstTwoChars.equals("FT"))
                    {
                        str="FC";
                    }
                    if(firstTwoChars.equals("MQ"))
                    {
                        str="FM";
                    }
                    if(firstTwoChars.equals("FE"))
                    {
                        str="TC";
                    }
                    returnResult=userhomeOrderService.callBacktransferInner(outTradeNo,tradeSn,str);
                    Map<String, Object> params=new HashMap<>();
                    params.put("merchantNo", YinShengUtil.getPrdPayeeMerchantNo());
                    params.put("type", 0);
                    params.put("out_trade_no", outTradeNo);
                    params.put("money", totalAmount);
                    YinShengUtil.report(params);
                }
                //钱包余额
                if(firstTwoChars.equals("FA")||firstTwoChars.equals("FM"))
                {
                    returnResult=userhomeOrderService.callBackFa(outTradeNo,tradeSn);
                }
                //基金赎回
                if(firstTwoChars.equals("FC"))
                {
                    returnResult=userhomeOrderService.callBackFa2(outTradeNo,tradeSn);
                }

                if(returnResult.isSuccess())
                {
                    return "success";
                }

                return "fail";
            }
        } catch (ValidationException e) {
            // 签名验证失败，返回 401 UNAUTHORIZED 状态码
        }
        return "error";
    }

   /* @ApiOperation("测试")
    @RequestMapping(value = "/yinsheng/ce", method = {RequestMethod.GET, RequestMethod.POST})
    public String ce(HttpServletRequest req) throws YsChannelClientException {

      *//*  sysBaseApi.sendEmailMsg("825093890@qq.com","测试","你好");*//*
        userhomeOrderService.callBack("FD202409222012018877","","123");
            return "ok";

    }*/

    /**
     * 分页列表查询
     *
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    //@AutoLog(value = "基金订单表-分页列表查询")
    @ApiOperation(value="用户基金订单表-分页列表查询", notes="用户订单表-分页列表查询")
    @GetMapping(value = "/list")
    public Result<IPage<UserhomeOrder>> queryPageList(QueryUserhomeOrder queryUserhomeOrder,
                                                      @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
                                                      @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
                                                      HttpServletRequest req) {
        UserhomeOrder userhomeOrder=new UserhomeOrder();
        QueryWrapper<UserhomeOrder> queryWrapper = QueryGenerator.initQueryWrapper(userhomeOrder, req.getParameterMap());
        Integer userhomeId = JwtUtil.getUserId(req.getHeader("X-Access-Token"));
        queryWrapper.eq("a.userhome_id",userhomeId);
        if(oConvertUtils.isNotEmpty(queryUserhomeOrder.getFundName()))
        {
            queryWrapper.like("g.name",queryUserhomeOrder.getFundName());
        }
        if(oConvertUtils.isNotEmpty(queryUserhomeOrder.getFcode()))
        {
            queryWrapper.eq("g.fcode",queryUserhomeOrder.getFcode());
        }
        if(oConvertUtils.isNotEmpty(queryUserhomeOrder.getStatus()))
        {
            queryWrapper.eq("a.status",queryUserhomeOrder.getStatus());
        }
        if(oConvertUtils.isNotEmpty(queryUserhomeOrder.getType()))
        {
            queryWrapper.eq("a.type",queryUserhomeOrder.getType());
        }
        queryWrapper.orderByDesc("create_time");
        Page<UserhomeOrder> page = new Page<UserhomeOrder>(pageNo, pageSize);
        IPage<UserhomeOrder> pageList = userhomeOrderService.pageList(page, queryWrapper);
        return Result.OK(pageList);
    }


    @ApiOperation("钱包余额提款")
    @RequestMapping(value = "/withraw", method = RequestMethod.POST)
    public Result<?> withraw( @RequestBody WithdrawOrder withdrawOrder,HttpServletRequest req) {
        Integer userhomeId = JwtUtil.getUserId(req.getHeader("X-Access-Token"));
        Userhome userhome = userhomeService.getById(userhomeId);
        return userhomeOrderService.withraw(userhome,withdrawOrder);
    }


    @ApiOperation("可部分赎回")
    @RequestMapping(value = "/withrawFund", method = RequestMethod.POST)
    public Result<?> withrawFund( @RequestBody WithdrawFund withdrawFund,HttpServletRequest req) {
        Integer userhomeId = JwtUtil.getUserId(req.getHeader("X-Access-Token"));
        Userhome userhome = userhomeService.getById(userhomeId);
        String orderNum = YinShengUtil.OrderNum("FT");
        return userhomeOrderService.withrawFund(userhome,withdrawFund,orderNum);
    }

    @ApiOperation("可部分转让")
    @RequestMapping(value = "/withrawTransference", method = RequestMethod.POST)
    public Result<?> withrawTransference( @RequestBody WithdrawFund withdrawFund,HttpServletRequest req) {
        Integer userhomeId = JwtUtil.getUserId(req.getHeader("X-Access-Token"));
        Userhome userhome = userhomeService.getById(userhomeId);
        String orderNum = YinShengUtil.OrderNum("FE");
        return userhomeOrderService.withrawFund(userhome,withdrawFund,orderNum);
    }


    @ApiOperation("基金钱包提款")
    @RequestMapping(value = "/withrawFundMoney", method = RequestMethod.POST)
    public Result<?> withrawFundMoney( @RequestBody WithdrawOrder withdrawOrder,HttpServletRequest req) {
        Integer userhomeId = JwtUtil.getUserId(req.getHeader("X-Access-Token"));
        Userhome userhome = userhomeService.getById(userhomeId);
        return userhomeOrderService.withrawFundMoney(userhome,withdrawOrder);
    }

    /**
     * 分页列表查询
     *
     * @param fund
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    //@AutoLog(value = "基金基本信息-分页列表查询")
    @ApiOperation(value="基金基本信息-分页列表查询", notes="基金基本信息-分页列表查询")
    @GetMapping(value = "/fundList")
    public Result<IPage<Fund>> queryPageFundlist(Fund fund,
                                             @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
                                             @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
                                             HttpServletRequest req) {
        QueryWrapper<Fund> queryWrapper = QueryGenerator.initQueryWrapper(fund, req.getParameterMap());
        Page<Fund> page = new Page<Fund>(pageNo, pageSize);
        IPage<Fund> pageList = fundService.page(page, queryWrapper);
        return Result.OK(pageList);
    }


    /**
     * 分页列表查询
     *
     * @param fundType
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    //@AutoLog(value = "基金类型-分页列表查询")
    @ApiOperation(value="基金类型-分页列表查询", notes="基金类型-分页列表查询")
    @GetMapping(value = "/fundTypeList")
    public Result<IPage<FundType>> queryPageFundTypeList(FundType fundType,
                                                 @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
                                                 @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
                                                 HttpServletRequest req) {
        QueryWrapper<FundType> queryWrapper = QueryGenerator.initQueryWrapper(fundType, req.getParameterMap());
        Page<FundType> page = new Page<FundType>(pageNo, pageSize);
        IPage<FundType> pageList = fundTypeService.page(page, queryWrapper);
        return Result.OK(pageList);
    }



    /**
     * 分页列表查询
     *
     * @return
     */
    //@AutoLog(value = "基金类型-分页列表查询")
    @ApiOperation(value="申购汇率byid", notes="申购汇率byid")
    @GetMapping(value = "/queryFundSubscriptionRate")
    public Result<List<FundSubscriptionRate>> queryFundSubscriptionRate( @RequestParam(name="fundId",required=true) String fundId) {
        QueryWrapper<FundSubscriptionRate> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("fund_id",fundId);
        List<FundSubscriptionRate> list = fundSubscriptionRateService.list(queryWrapper);
        return Result.OK(list);
    }


    /**
     * 分页列表查询
     *
     * @param mallConfiguration
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    //@AutoLog(value = "商城配置-分页列表查询")
    @ApiOperation(value="系统配置-分页列表查询", notes="系统配置-分页列表查询")
    @GetMapping(value = "/mallList")
    public Result<IPage<MallConfiguration>> queryMallList(MallConfiguration mallConfiguration,
                                                          @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
                                                          @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
                                                          HttpServletRequest req) {
        QueryWrapper<MallConfiguration> queryWrapper = QueryGenerator.initQueryWrapper(mallConfiguration, req.getParameterMap());
        Page<MallConfiguration> page = new Page<MallConfiguration>(pageNo, pageSize);
        IPage<MallConfiguration> pageList = mallConfigurationService.page(page, queryWrapper);
        return Result.OK(pageList);
    }


    @ApiOperation(value="用户持有基金-分页列表查询", notes="用户持有基金-分页列表查询")
    @GetMapping(value = "/queryMyFundList")
    public Result<IPage<UserhomeFund>> queryMyFundList(UserhomeFund userhomeFund,
                                                     @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
                                                     @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
                                                     HttpServletRequest req) {
        UserhomeFund temp=new UserhomeFund();
        if(oConvertUtils.isNotEmpty(userhomeFund.getStatus()))
        {
            temp.setStatus(userhomeFund.getStatus());
            userhomeFund.setStatus(null);
        }
        QueryWrapper<UserhomeFund> queryWrapper = QueryGenerator.initQueryWrapper(userhomeFund, req.getParameterMap());
        Page<UserhomeFund> page = new Page<UserhomeFund>(pageNo, pageSize);
        if(oConvertUtils.isNotEmpty(userhomeFund.getFundname()))
        {
            queryWrapper.like("g.name",userhomeFund.getFundname());
        }
        if(oConvertUtils.isNotEmpty(userhomeFund.getFcode()))
        {
            queryWrapper.eq("g.fcode",userhomeFund.getFcode());
        }
        if(oConvertUtils.isNotEmpty(userhomeFund.getPhone()))
        {
            queryWrapper.like("u.phone",userhomeFund.getPhone());
        }
        if(oConvertUtils.isNotEmpty(temp.getStatus()))
        {
            queryWrapper.eq("a.status",temp.getStatus());
        }
        queryWrapper.orderByDesc("create_time");
        Integer userhomeId = JwtUtil.getUserId(req.getHeader("X-Access-Token"));
        queryWrapper.eq("a.userhome_id",userhomeId);
        IPage<UserhomeFund> pageList = userhomeFundService.pageList(page, queryWrapper);
        return Result.OK(pageList);
    }


    @ApiOperation(value="统计", notes="统计")
    @GetMapping(value = "/countFungProfit")
    public Result<List<UserhomeProfit>> countFungProfit(
            @RequestParam(name="month", defaultValue="12") Integer month,
                                                       HttpServletRequest req) {
        List<UserhomeProfit> result=new ArrayList<>();
        Integer userhomeId = JwtUtil.getUserId(req.getHeader("X-Access-Token"));
        Calendar calendar = Calendar.getInstance();
        for (int i = 0; i < month; i++) {
            UserhomeProfit temp=new UserhomeProfit();
            // 当前月份的第一天
            calendar.set(Calendar.DAY_OF_MONTH, 1);
            String firstDate = String.format("%tF", calendar);

            // 当前月份的最后一天
            calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
            String lastDate = String.format("%tF", calendar);

            System.out.println("Month " + (i + 1) + ": " + firstDate + " - " + lastDate);

            // 设置为上一个月份
            calendar.add(Calendar.MONTH, -1);

            //收益
            QueryWrapper<UserhomeWalletFundLog> logQueryWrapper=new QueryWrapper<>();
            logQueryWrapper.eq("userhome_id",userhomeId);
            logQueryWrapper.eq("type",2);
            logQueryWrapper.ge("create_time",firstDate);
            logQueryWrapper.lt("create_time",lastDate);
            logQueryWrapper.select("SUM(amount) as amount"); // 指定要求和的字段
            List<Object> results = userhomeWalletFundLogService.listObjs(logQueryWrapper); // 执行查询
            if(!results.isEmpty()) {
                temp.setAmount((Double) (results.get(0)));
            }
            else
            {
                temp.setAmount(0.00);
            }
            //

            //投资
            QueryWrapper<UserhomeFund> fundQueryWrapper=new QueryWrapper<>();
            fundQueryWrapper.eq("userhome_id",userhomeId);
            fundQueryWrapper.ge("create_time",firstDate);
            fundQueryWrapper.lt("create_time",lastDate);
            fundQueryWrapper.select("SUM(num) as num"); // 指定要求和的字段
            List<Object> results2 = userhomeFundService.listObjs(fundQueryWrapper); // 执行查询
            if(!results2.isEmpty()) {
                temp.setMoney((Double) (results2.get(0)));
            }
            else
            {
                temp.setMoney(0.00);
            }

            temp.setUserhomeId(userhomeId);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date date=null;
            try {
                date = sdf.parse(firstDate);
            }
            catch (Exception e) {

            }
            temp.setCreateTime(date);
            result.add(temp);

        }
        return Result.OK(result);
    }









}